<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
 * PHP version 5
 *
 * This source file is subject to version 2.1 of the GNU Lesser General Public
 * License, that is bundled with this package in the file COPYING, available
 * through the world wide web at the following URI:
 * http://www.gnu.org/copyleft/lesser.html.
 *
 * @package    ZNF
 * @subpackage Actions
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: DispatchAction.php 43 2007-06-26 23:36:35Z aronnax $
 * @since      Release 0.7.0
 * @link       http://www.zeronotice.org
 */

/**
 * <i>ZNF_Actions_DispatchAction</i> is an abstract <i>ZNF_Action_Action</i> that dispatches to a public method that is named by the request parameter whose name is specified by the <i>parameter</i> property of the corresponding <i>ZNF_Action_ActionMapping</i>.
 *
 * This <i>action</i> is useful for developers who prefer to combine many
 * similar actions into a single <i>ZNF_Actions_DispatchAction</i> class, in
 * order to simplify their application design.
 *
 * There are several way the configure this action in your module configuration
 * file.
 *
 * - Usage of the <i>parameter</i> attribute
 *
 * <i>
 *   &lt;action path="customAction"
 *     type="Package_Action_CustomDispatchAction"
 *     parameter="method@location"/&gt;
 * </i>
 *
 * This action will use the value of the request parameter named <i>method</i>
 * to pick the appropriate <i>execute</i> method, which must have the same
 * signature (other than method name) of the standard
 * <i>ZNF_Actions_DispatchAction->execute()</i> method. For example, you might
 * have the following three methods in the same action class:
 * <ul>
 *   <li>public function create($form, $mapping)</li>
 *   <li>public function update($form, $mapping)</li>
 *   <li>public function delete($form, $mapping)</li>
 * </ul>
 * And call one of them with a URL like this:
 * <i>
 *   http://&lt;yourhost&gt;/&lT;yourapp&gt;/znf/action?method=update
 * </i>
 *
 * The second part of the parameter attribute (@location) is optional and it is
 * used to specify where to find the requested parameter, possible values are:
 * 'GET', 'POST', 'REQUEST' and 'SESSION'.
 * Considering the example above it should be replaced by 'GET', anyway if not
 * specified it will be assumed the 'GET' value anyway.
 *
 * - Usage of the <i>parameterValue</i> attribute
 *
 * <i>
 *   &lt;action path="customAction"
 *     type="Package_Action_CustomDispatchAction"
 *     parameterValue="update"/&gt;
 * </i>
 *
 * The <i>parameterValue</i> attribute is used to specify directly the name of
 * the method that it will be called, considering the configuration above it
 * will becalled the <i>update</i> method of the
 * <i>ZNF_Actions_CustomDispatchAction</i> class.
 *
 * <p><strong>NOTE</strong> - <i>parameter</i> and <i>parameterValues</i>
 * attribute are exclusive and if any of them is specified or the result value
 * is <i>empty</i> or <i>execute</i>, a method named <i>unspecified</i> is called.
 * The default action is to throw an exception. You can override the
 * <i>unspecified</i> method in your subclass.
 *
 * @access     public
 * @package    ZNF
 * @subpackage Actions
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: DispatchAction.php 43 2007-06-26 23:36:35Z aronnax $
 * @since      Release 0.7.0
 * @link       http://www.zeronotice.org
 */
abstract class ZNF_Actions_DispatchAction
{

    /**
     * Constructs a new <i>ZNF_Actions_DispatchAction</i> object.
     *
     * @access public
     */
    public function __construct()
    {
    }

    /**
     * Code to check and execute the action, subclasses must implement the method requested.
     *
     * If the method required is not implemented by the subclass the
     * <i>unspecified</i> method is called.
     *
     * @access public
     * @param ZNF_Action_ActionForm $form
     * @param ZNF_Action_ActionMapping $mapping
     * @return ZNF_Action_ActionForward
     */
    public function execute($form, $mapping)
    {
        $method = false;

        $parameterValue = $mapping->getParameterValue();

        if (!$parameterValue) {
            $parameter = $mapping->getParameter();

            $location = '';

            if (ereg('@', $parameter)) {
                $parameterArray = explode('@', $parameter);
                $parameter = $parameterArray[0];
                $location = $parameterArray[1];
            }

            switch ($location) {
                case 'GET':
                    if (isset($_GET[$parameter])) {
                        $method = $_GET[$parameter];
                    }
                break;

                case 'POST':
                    if (isset($_POST[$parameter])) {
                        $method = $_POST[$parameter];
                    }
                break;

                case 'REQUEST':
                    if (isset($_REQUEST[$parameter])) {
                        $method = $_REQUEST[$parameter];
                    }
                break;

                case 'SESSION':
                    if (isset($_SESSION[$parameter])) {
                        $method = $_SESSION[$parameter];
                    }
                break;

                default:
                    if (isset($_GET[$parameter])) {
                        $method = $_GET[$parameter];
                    }
                break;
            }
        } else {
            $method = $parameterValue;
        }

        if (!$method || $method == "execute" || !method_exists($this, $method)) {
            return $this->unspecified($form, $mapping);
        }

        return $this->$method($form, $mapping);
    }

    /**
     * Default method to execute if the requested method is not found or the <i>parameter</i> attibute in the configuration file is not specified.
     *
     * Subclasses can override this method to customize the error.
     *
     * @access public
     * @param ZNF_Action_ActionForm $form
     * @param ZNF_Action_ActionMapping $mapping
     */
    public function unspecified($form, $mapping)
    {
        $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
        throw new ZNF_Actions_DispatchActionException($translation->get('errorMethodNotValid'));
    }

    /**
     * Destroys the <i>ZNF_Actions_DispatchAction</i> object.
     *
     * @access public
     */
    public function __destruct()
    {
    }

}

/**
 * <i>ZNF_Actions_DispatchActionException</i> is the exception type for the <i>ZNF_Actions_DispatchAction</i> class.
 *
 * <i>ZNF_Actions_DispatchActionException</i> extends the <i>Exception</i> class of PHP5.
 *
 * @access     public
 * @package    ZNF
 * @subpackage Actions
 * @author     Alessandro Rossini <http://www.alessandrorossini.org>
 * @author     Graziano Liberati <http://www.liberati.org>
 * @copyright  2004-2007 The ZNF Development Team
 * @license    LGPL License 2.1 <http://www.gnu.org/copyleft/lesser.html>
 * @version    SVN $Id: DispatchAction.php 43 2007-06-26 23:36:35Z aronnax $
 * @since      Release 0.7.0
 * @link       http://www.zeronotice.org
 */
class ZNF_Actions_DispatchActionException extends Exception
{
}

?>
